.. role:: raw-html-m2r(raw) :format: html VHDL equivalences ================= Entity and architecture ----------------------- In SpinalHDL, a VHDL entity and architecture are both defined inside a ``Component``. Here is an example of a component which has 3 inputs (``a``, ``b``, ``c``) and an output (``result``). This component also has an ``offset`` construction parameter (like a VHDL generic). .. code-block:: scala case class MyComponent(offset: Int) extends Component { val io = new Bundle { val a, b, c = in UInt(8 bits) val result = out UInt(8 bits) } io.result := a + b + c + offset } Then to instantiate that component, you don't need to bind it: .. code-block:: scala case class TopLevel extends Component { ... val mySubComponent = MyComponent(offset = 5) ... mySubComponent.io.a := 1 mySubComponent.io.b := 2 mySubComponent.io.c := 3 ??? := mySubComponent.io.result ... } Data types ---------- SpinalHDL data types are similar to the VHDL ones: .. list-table:: :header-rows: 1 * - VHDL - SpinalHDL * - std_logic - Bool * - std_logic_vector - Bits * - unsigned - UInt * - signed - SInt | In VHDL, to define an 8 bit ``unsigned`` you have to give the range of bits ``unsigned(7 downto 0)``, | whereas in SpinalHDL you simply supply the number of bits ``UInt(8 bits)``. .. list-table:: :header-rows: 1 * - VHDL - SpinalHDL * - records - Bundle * - array - Vec * - enum - SpinalEnum Here is an example of the SpinalHDL ``Bundle`` definition. ``channelWidth`` is a construction parameter, like VHDL generics, but for data structures: .. code-block:: scala case class RGB(channelWidth: Int) extends Bundle { val r, g, b = UInt(channelWidth bits) } Then for example, to instantiate a ``Bundle``, you need to write ``val myColor = RGB(channelWidth=8)``. Signal ------ Here is an example about signal instantiations: .. code-block:: scala case class MyComponent(offset: Int) extends Component { val io = new Bundle { val a, b, c = UInt(8 bits) val result = UInt(8 bits) } val ab = UInt(8 bits) ab := a + b val abc = ab + c // You can define a signal directly with its value io.result := abc + offset } Assignments ----------- In SpinalHDL, the ``:=`` assignment operator is equivalent to the VHDL signal assignment (``<=``): .. code-block:: scala val myUInt = UInt(8 bits) myUInt := 6 Conditional assignments are done like in VHDL by using ``if``/``case`` statements: .. code-block:: scala val clear = Bool() val counter = Reg(UInt(8 bits)) when(clear) { counter := 0 }.elsewhen(counter === 76) { counter := 79 }.otherwise { counter(7) := ! counter(7) } switch(counter) { is(42) { counter := 65 } default { counter := counter + 1 } } Literals -------- Literals are a little bit different than in VHDL: .. code-block:: scala val myBool = Bool() myBool := False myBool := True myBool := Bool(4 > 7) val myUInt = UInt(8 bits) myUInt := "0001_1100" myUInt := "xEE" myUInt := 42 myUInt := U(54,8 bits) myUInt := ((3 downto 0) -> myBool, default -> true) when(myUInt === U(myUInt.range -> true)) { myUInt(3) := False } Registers --------- In SpinalHDL, registers are explicitly specified while in VHDL registers are inferred. Here is an example of SpinalHDL registers: .. code-block:: scala val counter = Reg(UInt(8 bits)) init(0) counter := counter + 1 // Count up each cycle // init(0) means that the register should be initialized to zero when a reset occurs Process blocks -------------- Process blocks are a simulation feature that is unnecessary to design RTL. It's why SpinalHDL doesn't contain any feature analogous to process blocks, and you can assign what you want, where you want. .. code-block:: scala val cond = Bool() val myCombinatorial = Bool() val myRegister = UInt(8 bits) myCombinatorial := False when(cond) { myCombinatorial := True myRegister = myRegister + 1 }